package com.example.keshe;

import com.example.keshe.Dao.impl.InventoryDaoImpl;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import static com.example.keshe.util.DruidUtil.getConnection;

/**
 * 库存视图控制器类，使用FXML注解声明界面元素，控制按钮和处理用户操作。
 */
public class InventoryView {
    /**
     * FXML注解声明界面元素
     */
    @FXML
    private Pagination pageTable;
    private int itemsPerPage = 20;
    @FXML
    private TableView<Inventory> inventoryTable;
    @FXML
    private TableColumn<Inventory, String> inventoryIdCol;
    @FXML
    private TableColumn<Inventory, String> clothingIdCol;
    @FXML
    private TableColumn<Inventory, String> purchasePriceCol;
    @FXML
    public TableColumn<Inventory, String> purchaseQuantityCol;
    @FXML
    private TableColumn<Inventory, String> totalAmountCol;
    @FXML
    private TableColumn<Inventory, String> existingStockCol;
    @FXML
    private TableColumn<Inventory, String> inventoryDateCol;

    /**
     * 控制按钮
     */
    public Button addButton;
    public Button deleteButton;
    public Button refreshButton;
    public Button queryTotalAmountButton;
    public Button closeButton;
    public Button queryAllTotalAmountButton;

    /**
     * 显示库存总金额的标签
     */
    public Label totalAmountLabel;

    /**
     * 初始化方法，界面加载时调用。
     */
    @FXML
    private void initialize() {
        initPagination();// 初始化分页控件
        loadPageData(0);// 加载库存数据，默认加载第一页
        inventoryTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);// 设置TableView的多选模式
    }

    /**
     * 初始化分页控件，设置总页数，并添加页码变化监听器。
     */
    private void initPagination() {
        pageTable.setPageCount(calculatePageCount());
        pageTable.currentPageIndexProperty().addListener((observable, oldValue, newValue) -> {
            loadPageData(newValue.intValue());// 根据新的页码加载数据
        });
    }

    /**
     * 计算总页数，基于总记录数和每页显示的条数。
     *
     * @return 计算得到的总页数。
     */
    private int calculatePageCount() {
        try {
            try (Connection connection = getConnection()) {
                InventoryDaoImpl inventoryDao = new InventoryDaoImpl(connection);
                return (int) Math.ceil((double) inventoryDao.getTotalRecords() / itemsPerPage);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 加载指定页码的数据到 TableView 中。
     *
     * @param pageIndex 要加载的页码。
     */
    private void loadPageData(int pageIndex) {
        try {
            try (Connection connection = getConnection()) {
                InventoryDaoImpl inventoryDao = new InventoryDaoImpl(connection);
                List<Inventory> pageData = inventoryDao.selectByPage(pageIndex + 1, itemsPerPage);// 获取每页数据
                updateTableView(pageData); // 将数据加载到 TableView 中
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新TableView中的数据。
     *
     * @param inventoryList 要更新的库存数据列表。
     */
    private void updateTableView(List<Inventory> inventoryList) {
        inventoryTable.getItems().setAll(inventoryList);// 传入List集合，更新TableView
        // 为每列设置单元格值工厂，以从库存对象中获取属性值显示。
        inventoryIdCol.setCellValueFactory(new PropertyValueFactory<>("inventoryId"));
        clothingIdCol.setCellValueFactory(new PropertyValueFactory<>("clothingId"));
        purchasePriceCol.setCellValueFactory(new PropertyValueFactory<>("purchasePrice"));
        purchaseQuantityCol.setCellValueFactory(new PropertyValueFactory<>("purchaseQuantity"));
        totalAmountCol.setCellValueFactory(new PropertyValueFactory<>("totalAmount"));
        existingStockCol.setCellValueFactory(new PropertyValueFactory<>("existingStock"));
        inventoryDateCol.setCellValueFactory(new PropertyValueFactory<>("inventoryDate"));
    }

    /**
     * 显示警告对话框的通用方法。
     *
     * @param title     对话框标题。
     * @param content   对话框内容。
     * @param alertType 对话框类型。
     */
    private void showAlert(String title, String content, Alert.AlertType alertType) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setHeaderText(null);
        alert.setContentText(content);
        alert.showAndWait();
    }

    /**
     * 异步添加库存记录。
     *
     * @param inventory 要添加的库存记录对象。
     * @return CompletableFuture，表示异步操作的结果。
     */
    private CompletableFuture<Void> addInventoryAsync(Inventory inventory) {
        try {
            try (Connection connection = getConnection()) {
                InventoryDaoImpl<Inventory> inventoryDao = new InventoryDaoImpl<>(connection);
                return inventoryDao.addInventoryAsync(inventory); // 调用DAO层异步方法添加库存记录
            }
        } catch (SQLException e) {
            e.printStackTrace();
            return CompletableFuture.completedFuture(null);
        }
    }

    /**
     * 异步删除库存记录。
     *
     * @param inventory 要删除的库存记录。
     * @return 一个CompletableFuture，表示异步操作的结果。
     */
    private CompletableFuture<Void> deleteInventoryAsync(Inventory inventory) {
        try (Connection conn = getConnection()) {
            InventoryDaoImpl<Inventory> inventoryDao = new InventoryDaoImpl<>(conn);
            return inventoryDao.deleteInventoryAsync(inventory);// 调用DAO层异步方法删除库存记录
        } catch (SQLException e) {
            e.printStackTrace();
            return CompletableFuture.completedFuture(null);
        }
    }

    /**
     * 异步计算单个库存金额。
     *
     * @param clothingId 服装ID。
     * @param startTime  开始日期。
     * @param endTime    结束日期。
     * @return 一个CompletableFuture，表示异步操作的结果。
     */
    private CompletableFuture<String> calculateMoney(String clothingId, String startTime, String endTime) {
        try (Connection conn = getConnection()) {
            InventoryDaoImpl<Inventory> inventoryDao = new InventoryDaoImpl<>(conn);
            return inventoryDao.calculateMoney(clothingId, startTime, endTime);// 调用DAO层异步方法计算库存金额
        } catch (SQLException e) {
            e.printStackTrace();
            return CompletableFuture.completedFuture("");
        }
    }

    /**
     * 异步计算库存金额。
     *
     * @param startTime 开始日期。
     * @param endTime   结束日期。
     * @return 一个CompletableFuture，表示异步操作的结果。
     */
    private CompletableFuture<String> calculateAllTotalAmount(String startTime, String endTime) {
        try (Connection conn = getConnection()) {
            InventoryDaoImpl<Inventory> inventoryDao = new InventoryDaoImpl<>(conn);
            return inventoryDao.calculateAllTotalAmount(startTime, endTime); // 调用DAO层异步方法计算所有库存金额
        } catch (SQLException e) {
            e.printStackTrace();
            return CompletableFuture.completedFuture("");
        }
    }

    /**
     * 添加库存按钮点击事件处理。
     *
     * @param event 点击事件。
     */
    @FXML
    private void addInventory(ActionEvent event) {
        // 创建GridPane
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));
        // 创建文本框
        TextField inventoryIdField = new TextField();
        TextField clothingIdField = new TextField();
        TextField purchasePriceField = new TextField();
        TextField purchaseQuantityField = new TextField();
        DatePicker inventoryDatePicker = new DatePicker(); // 使用DatePicker选择日期
        // 将文本框和日期选择器添加到GridPane
        grid.add(new Label("库存Id"), 0, 0);
        grid.add(inventoryIdField, 1, 0);
        grid.add(new Label("服装Id:"), 0, 1);
        grid.add(clothingIdField, 1, 1);
        grid.add(new Label("进货价格:"), 0, 2);
        grid.add(purchasePriceField, 1, 2);
        grid.add(new Label("进货数量:"), 0, 3);
        grid.add(purchaseQuantityField, 1, 3);
        grid.add(new Label("进货日期"), 0, 4);
        grid.add(inventoryDatePicker, 1, 4);
        // 创建对话框
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle("添加库存");
        dialog.getDialogPane().setContent(grid);
        // 添加按钮
        ButtonType addButton = new ButtonType("添加", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(addButton, ButtonType.CANCEL);
        Optional<ButtonType> result = dialog.showAndWait();// 显示对话框并等待用户输入
        // 处理用户输入
        result.ifPresent(buttonType -> {
            if (buttonType == addButton) {
                // 用户点击了添加按钮
                // 解析输入并创建 Inventory 对象
                Inventory inventoryToAdd = Inventory.createPartialInventory(
                        inventoryIdField.getText().trim(),
                        clothingIdField.getText().trim(),
                        purchasePriceField.getText().trim(),
                        purchaseQuantityField.getText().trim(),
                        inventoryDatePicker.getValue() != null ? inventoryDatePicker.getValue().toString() : ""
                );
                CompletableFuture<Void> addInventoryFuture = addInventoryAsync(inventoryToAdd);// 异步添加库存记录
                // 当异步添加操作完成后，执行刷新操作
                addInventoryFuture.thenRun(() -> {
                    loadPageData(pageTable.getCurrentPageIndex()); // 刷新表格视图
                });
            }
        });
    }

    /**
     * 删除库存按钮点击事件处理。
     *
     * @param event 点击事件。
     */
    @FXML
    private void deleteInventory(ActionEvent event) {
        // 创建GridPane，用于用户输入
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));
        // 创建文本框和日期选择器
        TextField inventoryIdField = new TextField();
        TextField clothingIdField = new TextField();
        TextField purchasePriceField = new TextField();
        TextField purchaseQuantityField = new TextField();
        DatePicker inventoryDatePicker = new DatePicker(); // 使用DatePicker选择日期
        // 将文本框和日期选择器添加到GridPane
        grid.add(new Label("库存Id"), 0, 0);
        grid.add(inventoryIdField, 1, 0);
        grid.add(new Label("服装Id:"), 0, 1);
        grid.add(clothingIdField, 1, 1);
        grid.add(new Label("进货价格:"), 0, 2);
        grid.add(purchasePriceField, 1, 2);
        grid.add(new Label("进货数量:"), 0, 3);
        grid.add(purchaseQuantityField, 1, 3);
        grid.add(new Label("进货日期"), 0, 4);
        grid.add(inventoryDatePicker, 1, 4);
        // 创建对话框，用于用户输入
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle("删除库存");
        dialog.getDialogPane().setContent(grid);
        // 添加按钮
        ButtonType deleteButton = new ButtonType("删除", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(deleteButton, ButtonType.CANCEL);
        Optional<ButtonType> result = dialog.showAndWait(); // 显示对话框并等待用户输入
        // 处理用户输入
        result.ifPresent(buttonType -> {
            if (buttonType == deleteButton) {
                // 用户点击了删除按钮
                // 解析输入并创建 Inventory 对象
                Inventory inventoryToDelete = Inventory.createPartialInventory(
                        inventoryIdField.getText().trim(),
                        clothingIdField.getText().trim(),
                        purchasePriceField.getText().trim(),
                        purchaseQuantityField.getText().trim(),
                        inventoryDatePicker.getValue() != null ? inventoryDatePicker.getValue().toString() : ""
                );
                CompletableFuture<Void> deleteInventoryFuture = deleteInventoryAsync(inventoryToDelete); // 异步删除库存记录
                // 当异步删除操作完成后，执行刷新操作
                deleteInventoryFuture.thenRun(() -> {
                    loadPageData(pageTable.getCurrentPageIndex());// 刷新表格视图
                });
            }
        });
    }

    /**
     * 查询单个总金额按钮点击事件处理。
     *
     * @param event 点击事件。
     */
    @FXML
    private void queryTotalAmount(ActionEvent event) {
        // 创建GridPane，用于用户输入
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));
        // 创建文本框和日期选择器
        TextField clothingIdField = new TextField();
        DatePicker startDatePicker = new DatePicker();
        DatePicker endDatePicker = new DatePicker();
        // 将文本框和日期选择器添加到GridPane
        grid.add(new Label("服装Id:"), 0, 0);
        grid.add(clothingIdField, 1, 0);
        grid.add(new Label("开始日期:"), 0, 1);
        grid.add(startDatePicker, 1, 1);
        grid.add(new Label("结束日期:"), 0, 2);
        grid.add(endDatePicker, 1, 2);
        // 创建对话框，用于用户输入
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle("计算总金额");
        dialog.getDialogPane().setContent(grid);
        // 添加按钮
        ButtonType calculateButton = new ButtonType("计算", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(calculateButton, ButtonType.CANCEL);
        Optional<ButtonType> result = dialog.showAndWait(); // 显示对话框并等待用户输入
        // 处理用户输入
        result.ifPresent(buttonType -> {
            if (buttonType == calculateButton) {
                // 用户点击了计算按钮
                // 解析用户输入
                String clothingId = clothingIdField.getText().trim();
                String startTime = startDatePicker.getValue() != null ? startDatePicker.getValue().toString() : "";
                String endTime = endDatePicker.getValue() != null ? endDatePicker.getValue().toString() : "";
                // 检查用户输入是否完整
                if (clothingId.isEmpty() || startTime.isEmpty() || endTime.isEmpty()) {
                    showAlert("错误", "请提供完整的服装ID、开始日期和结束日期。", Alert.AlertType.ERROR);
                    return;
                }
                CompletableFuture<String> calculateTotalAmountFuture = calculateMoney(clothingId, startTime, endTime);// 异步计算总金额
                // 处理计算结果和异常
                calculateTotalAmountFuture.thenAcceptAsync(totalAmount -> {
                    Platform.runLater(() -> totalAmountLabel.setText(totalAmount));// 更新 Label 的文本
                }, Platform::runLater).exceptionally(ex -> {
                    Platform.runLater(() -> showAlert("错误", ex.getMessage(), Alert.AlertType.ERROR));// 处理异常
                    return null;
                });
            }
        });
    }

    /**
     * 查询所有销售项在指定时间范围内的总金额按钮点击事件处理。
     *
     * @param event 点击事件。
     */
    @FXML
    private void queryAllTotalAmount(ActionEvent event) {
        // 创建 GridPane，用于用户输入
        GridPane grid = new GridPane();
        grid.setAlignment(Pos.CENTER);
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(25, 25, 25, 25));
        // 创建日期选择器
        DatePicker startDatePicker = new DatePicker();
        DatePicker endDatePicker = new DatePicker();
        // 将日期选择器添加到 GridPane
        grid.add(new Label("开始日期:"), 0, 0);
        grid.add(startDatePicker, 1, 0);
        grid.add(new Label("结束日期:"), 0, 1);
        grid.add(endDatePicker, 1, 1);
        // 创建对话框，用于用户输入
        Dialog<ButtonType> dialog = new Dialog<>();
        dialog.setTitle("计算总金额");
        dialog.getDialogPane().setContent(grid);
        // 添加按钮
        ButtonType calculateButton = new ButtonType("计算", ButtonBar.ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(calculateButton, ButtonType.CANCEL);
        Optional<ButtonType> result = dialog.showAndWait(); // 显示对话框并等待用户输入
        // 处理用户输入
        result.ifPresent(buttonType -> {
            if (buttonType == calculateButton) {
                // 用户点击了计算按钮
                // 解析用户输入
                String startTime = startDatePicker.getValue() != null ? startDatePicker.getValue().toString() : "";
                String endTime = endDatePicker.getValue() != null ? endDatePicker.getValue().toString() : "";
                // 检查用户输入是否完整
                if (startTime.isEmpty() || endTime.isEmpty()) {
                    showAlert("错误", "请提供完整的开始日期和结束日期。", Alert.AlertType.ERROR);
                    return;
                }
                CompletableFuture<String> calculateAllTotalAmountFuture = calculateAllTotalAmount(startTime, endTime);// 异步计算所有销售项总金额
                // 处理计算结果和异常
                calculateAllTotalAmountFuture.thenAcceptAsync(totalAmount -> {
                    Platform.runLater(() -> totalAmountLabel.setText(totalAmount));// 更新 Label 的文本
                }, Platform::runLater).exceptionally(ex -> {
                    Platform.runLater(() -> showAlert("错误", ex.getMessage(), Alert.AlertType.ERROR));// 处理异常
                    return null;
                });
            }
        });
    }

    /**
     * 刷新表格按钮点击事件处理。
     *
     * @param actionEvent 点击事件。
     */
    public void refreshTable(ActionEvent actionEvent) {
        int currentPageIndex = pageTable.getCurrentPageIndex(); // 获取当前页码
        loadPageData(currentPageIndex);// 重新加载数据到表格
        // 设置 totalAmountLabel 的值
        totalAmountLabel.setText(""); // 使用你希望显示的新的值
    }

    /**
     * 关闭应用按钮点击事件处理。
     *
     * @param actionEvent 点击事件。
     */
    public void closeApp(ActionEvent actionEvent) {
        Scene scene = ((Node) actionEvent.getSource()).getScene();// 获取当前控件所在的 Scene
        Stage stage = (Stage) scene.getWindow();// 获取当前窗口并关闭
        stage.hide();
    }
}
